package com.fight.strive.sys.modules.dictionary.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fight.strive.sys.modules.common.PageR;
import com.fight.strive.sys.modules.dictionary.dao.DataDictionaryMapper;
import com.fight.strive.sys.modules.dictionary.entity.DataDictionaryEntity;
import com.fight.strive.sys.modules.dictionary.service.DataDictionaryService;
import com.fight.strive.sys.modules.exception.StriveException;
import com.fight.strive.sys.modules.mybatis.MyBatisPlusUtils;
import com.fight.strive.sys.modules.redis.RedisUtils;
import com.fight.strive.sys.utils.CollectionUtils;
import com.fight.strive.sys.utils.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;


@Slf4j
@Service
@DS("master")
public class DataDictinaryServiceImpl
        extends ServiceImpl<DataDictionaryMapper, DataDictionaryEntity>
        implements DataDictionaryService {

    private final String parentIdKey = "sys:dictionary:parent_id";

    private final String idKey = "sys:dictionary:id";

    private final String codeKey = "sys:dictionary:code";

    @Override
    public void saveDict(DataDictionaryEntity entity) {
        try {
            if (ObjectUtils.isNull(entity.getParentId())) {
                entity.setParentId(0L);
            }
            this.saveOrUpdate(entity);
            entity = this.getById(entity.getId());
            this.updateCache(entity);
        } catch (DuplicateKeyException e) {
            throw new StriveException("该字典代码已存在");
        }
    }

    @Override
    public IPage<DataDictionaryEntity> listByPage(PageR<DataDictionaryEntity> page) {
        QueryWrapper<DataDictionaryEntity> queryWrapper = new QueryWrapper<>();
        MyBatisPlusUtils.buildAndQuery(queryWrapper, page.getCond());
        if (ObjectUtils.isNull(page.getCond().get("parentId"))) {
            queryWrapper.isNull("parent_id");
        }
        return this.page(page, queryWrapper);
    }

    @Override
    public void removeDict(DataDictionaryEntity entity) {
        List<DataDictionaryEntity> child = this.getByParentId(entity.getId());
        if (CollectionUtils.isNotEmpty(child)) {
            throw new StriveException("该字典有子项，无法删除！");
        }
        this.removeCache(this.getDictById(entity.getId()));
        this.removeById(entity.getId());
    }

    @Override
    public List<DataDictionaryEntity> getByParentId(Long parentId) {
        List<DataDictionaryEntity> list = RedisUtils.hashGetList(
                parentIdKey, parentId, DataDictionaryEntity.class);
        if (ObjectUtils.isNull(list)) {
            QueryWrapper<DataDictionaryEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parent_id", parentId)
                    .orderByAsc("seq");
            list = this.list(queryWrapper);
            if (CollectionUtils.isNotEmpty(list)) {
                RedisUtils.hashPut(parentIdKey, parentId, list);
            }
        }
        return list;
    }

    @Override
    public List<DataDictionaryEntity> getByParentCode(String parentCode) {
        DataDictionaryEntity entity = this.getByCode(parentCode);
        if (ObjectUtils.notNull(entity)) {
            return this.getByParentId(entity.getId());
        }
        return Collections.emptyList();
    }

    @Override
    public String getNameByCode(String code) {
        DataDictionaryEntity entity = this.getByCode(code);
        if (ObjectUtils.notNull(entity)) {
            return entity.getName();
        }
        return null;
    }

    @Override
    public DataDictionaryEntity getByCode(String code) {
        DataDictionaryEntity entity;
        Long id = RedisUtils.hashGet(codeKey, code, Long.class);
        if (ObjectUtils.notNull(id)) {
            entity = this.getDictById(id);
        } else {
            QueryWrapper<DataDictionaryEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("code", code);
            entity = this.getOne(queryWrapper, false);
            if (ObjectUtils.notNull(entity)) {
                this.updateCache(entity);
            }
        }
        return entity;
    }

    @Override
    public DataDictionaryEntity getDictById(Long id) {
        DataDictionaryEntity entity = RedisUtils.hashGet(
                idKey, id, DataDictionaryEntity.class);
        if (ObjectUtils.isNull(entity)) {
            entity = this.getById(id);
            if (ObjectUtils.notNull(entity)) {
                this.updateCache(entity);
            }
        }
        return entity;
    }

    @Override
    public void updateCache(DataDictionaryEntity entity) {
        if (ObjectUtils.notNull(entity)) {
            RedisUtils.hashPut(idKey, entity.getId(), entity);
            RedisUtils.hashPut(codeKey, entity.getCode(), entity.getId());
            // 删除父字典缓存
            RedisUtils.hashDelete(parentIdKey, entity.getParentId());
        }
    }

    @Override
    public void removeCache(DataDictionaryEntity entity) {
        if (ObjectUtils.notNull(entity)) {
            RedisUtils.hashDelete(idKey, entity.getId());
            RedisUtils.hashDelete(codeKey, entity.getCode());
            // 删除父字典缓存
            RedisUtils.hashDelete(parentIdKey, entity.getParentId());
        }
    }
}
